<?php

class E4Exception extends Exception {}
class E4ExceptionNotFound extends E4Exception{}
class E4ExceptionAccessDenided extends E4Exception
	{
	public $sRequered;
	public function __construct($sRequeredLevel = NULL)
		{
		$this->sRequered = $sRequeredLevel;
		}
	}

//TODO: Remove most init into __autoload + X4 Sources scheme
# Init Tools
require_once(X4_SITE_DIR."/components/tools/array.tools.php");
require_once(X4_SITE_DIR."/components/tools/mysql_short.tools.php");
//require_once(X4_ENGINE_DIR."/Tools/ImageProcessor/imageprocessor_tool.php");
# Init UPC Library
require_once(X4_SITE_DIR."/components/upc/upc.php");
# Init Templater
require_once(X4_ENGINE_DIR."/Templater/Templater.class.php");
# Init Core package
require_once(X4_ENGINE_DIR."/Core/Node.class.php");
require_once(X4_ENGINE_DIR."/Core/Site.class.php");
# Init Entity package
require_once(X4_ENGINE_DIR."/Entity/SimpleSQLEntity.class.php");
//require_once(X4_ENGINE_DIR."/Entity/EntityFKRelation.class.php");
//require_once(X4_ENGINE_DIR."/Entity/SimpleEntityTags.php");
//require_once(X4_ENGINE_DIR."/Entity/EntityImages.php");
//require_once(X4_ENGINE_DIR."/Entity/EntitySingleImage.php");
//require_once(X4_ENGINE_DIR."/Entity/EntityTreeCategories.php");
# Init Security package
require_once(X4_ENGINE_DIR."/Security/SecurityMy.class.php");

# Init MySQL
// TODO: Replace with subsystem
$MySQLConfig = array();
//include(X4_SITE_DIR."/config/mysql.config.php");
if(isset($MySQLConfig) and $MySQLConfig)
	{
	$link = mysql_connect($MySQLConfig['host'],$MySQLConfig['user'],$MySQLConfig['password']);
	mysql_select_db($MySQLConfig['database']);
	if (isset($MySQLConfig['charset']))
		{
		mysql_set_charset($MySQLConfig['charset'], $link);
		mysql_query("SET CHARACTER SET ".$MySQLConfig['charset']);
		}
	unset($MySQLConfig);
	}

# X4

class X4
{
const version = "0.4.2";
public static function getVersion(){return self::version;}
	
/**
 * Site
 * @var T4Site
 */
static protected $Site;
static protected $Templater, $sTemplaterClass="T4Templater";
static protected $Security, $sSecurityClass="T4SecurityMy"; // TODO: Configure engine classes
static protected $Instance;

static public function I()
	{
	if(!isset(self::$Instance))
		self::$Instance = new self;
	return self::$Instance;
	}

static public function Site($Site = NULL)
	{
	if(isset($Site))
		{
		// TODO: Check $Site instancof T4Site
		self::$Site = $Site;
		self::Templater()->getQuicky()->assign("Site",self::Site());
		self::Templater()->getQuicky()->assign("X4",self::I());
		}
	return self::$Site;
	}
	
static public function Templater()
	{
	if(!isset(self::$Templater))
		self::$Templater = new self::$sTemplaterClass;
	return self::$Templater;
	}
/**
 * Security module
 * @return T4SecurityLite
 */
static public function Security()
	{
	if(!isset(self::$Security))
		self::$Security = new self::$sSecurityClass;
	return self::$Security;
	}

# Subsystems Facade

/**
 * Current perspective to present site
 * @return string Perspective
 */
static public function getPerspective()
	{
	return self::Site()->getPerspective();
	}
	
static public function getPerspectivePrefix()
	{
	return self::Site()->getPerspectivePrefix();
	}
	
static public function call($mRequest)
	{
	return self::Site()->call($mRequest);
	}
	
static public function CheckAccessLevel($sRequestedLevel)
	{
	return self::Security()->CheckAccessLevel($sRequestedLevel);
	}

static public function RequireAccessLevel($sRequestedLevel)
	{
	if(!self::Security()->CheckAccessLevel($sRequestedLevel))
		throw new E4ExceptionAccessDenided($sRequestedLevel);
	}

static public function getCurrentUser()
	{
	return self::Security()->getCurrentUser();
	}
	
static public function getCurrenUserId()
	{
	return self::Security()->getCurrentUserId();
	}
	
public static function Template($sTemplate,$aData=NULL)
	{
	return self::Templater()->Template($sTemplate,$aData);
	}
	
##
# Modules Handling
##
	
static public function ModuleDir($sModule)
	{
	return X4_MODULES_DIR."/".$sModule;
	}
	
//TODO: Remove this	
static public function CloneModule($sOriginalName,$sCloneName,$bInstance = true)
	{
	if(!class_exists($sCloneName))
		eval("class $sCloneName extends $sOriginalName {}");
	if($bInstance)
		return new $sCloneName;
	}
	
# ERRORS
/**
 * Old-fashioned 404 exit
 * @return unknown_type
 */
static public function Error404()
	{
	throw new E4ExceptionNotFound();
	}
	
}

// TODO:: __autoload of engine classes

# Hooking Nod classes
function __autoload($sClassName)
	{
	if(file_exists(X4_MODULES_DIR."/".$sClassName.".class.php"))
		require_once(X4_MODULES_DIR."/".$sClassName.".class.php");
	elseif(file_exists(X4::ModuleDir($sClassName)."/".$sClassName.".class.php"))
		require_once(X4::ModuleDir($sClassName)."/".$sClassName.".class.php");
	elseif(
	  file_exists(X4::ModuleDir($sClassName)) 
	  and is_dir(X4::ModuleDir($sClassName)) 
	  and !file_exists(X4::ModuleDir($sClassName)."/".$sClassName.".class.php")
	  )
		X4::CloneModule($sClassName,"T4Node",false);
	}